﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;


namespace iOSRemoteConnector
{

    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    // NOTE: If the service is renamed, remember to update the global.asax.cs file
    public class Service1
    {

        
        
      
        [WebGet( UriTemplate = "/{identifier}/iphonetest")]
        public String testPost(String identifier)
        {

            Debug.WriteLine("Successful Connection by " + identifier);


            return "Success";

        }

        
        /*Upload Data Functions - Functions responsible for sending data from Server -> iOS */


        
        [WebInvoke(Method = "GET", UriTemplate = "/{identifier}/download/{filename}/")]
        public Stream Upload(String identifier, String filename)
        {

            String filePath = "C:\\Temp\\iPhoneData\\" + filename; 

            //FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            FileStream fs = File.OpenRead(filePath);


            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";

            return fs; 

            /*
            byte[] buffer;
            try
            {
                int fileLength = (int)fs.Length;
                buffer = new byte[fileLength];
                int chunk;
                int read = 0;

                while ((chunk = fs.Read(buffer, read, fileLength - read)) > 0)
                    read += chunk;

            }
            finally
            {
                //fs.Close(); 

            }

           

            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";

   

            return fs;
            */
        }






        /*Download Data Functions - Functions responsible for sending data from iOS -> Server */


        //static Dictionary<String, byte[]> fileUploads = new Dictionary<String, byte[]>();
        //static Dictionary<String, int> fileIndex = new Dictionary<String, int>(); 


        /* startDownload - Begins the transfer recording the name, type and number to bytes to be read */
        [WebInvoke(Method = "POST", UriTemplate = "/{identifier}/uploadstart/{name}/{type}/{numbytestotal}")]
        public void startDownload(String identifier, String name, String type, String numbytestotal) {

            
            Debug.WriteLine("Start Transfer : " + name + "." + type + " at " + DateTime.Now);


            //All objects required for downloading
            iOSDevice device = Devices.GetDevice(identifier); 


            String filename = name + "." + type; 
            byte[] buffer = new byte[Convert.ToInt32(numbytestotal)];




            //Store the new partial byte array in the receivedFiles of the 
            device.receivedFiles.Add(filename, buffer);

            device.downloadingFileIndex.Add(filename, 0);//We store the filename,index pair as a tuple




        }

        /* runDownload - Transfer the actual data for the transfer */
        [WebInvoke(Method = "POST", UriTemplate = "/{identifier}/upload/{name}/{type}/{numbytestransfer}")]
        public void runDownload(String identifier, Stream data, String name, String type, String numbytestransfer) {


            iOSDevice device = Devices.GetDevice(identifier);
            String filename = name + "." + type; 

            byte[] interBuffer = new byte[Convert.ToInt32(numbytestransfer)];

            
            int bytesRead = 0;
            int totalBytesRead = device.GetIndexForFile(filename); 

            
            do
            {
                
                bytesRead = data.Read(interBuffer, 0, interBuffer.Length);
                totalBytesRead += bytesRead;




            } while (bytesRead > 0);


            byte[] writeBuffer =device.receivedFiles[filename];
            int writeIndex = device.GetIndexForFile(filename); 

            interBuffer.CopyTo(writeBuffer, writeIndex);
            device.SetIndexForFile(filename, totalBytesRead);
          

            //Debug.WriteLine("Upload: " + name +"." + type + " with " + totalBytesRead);
           

         }

        /* finishDownload - Completes the transfer and saves the file */
        [WebInvoke(Method = "POST", UriTemplate = "/{identifier}/uploadfinish/{name}/{type}")]
        public void finishDownload (String identifier, String name, String type) {

            Debug.WriteLine("Finish Transfer : " + name + "." + type + " at " + DateTime.Now );


            iOSDevice device = Devices.GetDevice(identifier);
            String filename = name + "." + type;


            device.OnFileReceived(filename); 


            //MemoryStream ms = new MemoryStream(device.receivedFiles[filename]);
            //Image test = Image.FromStream(ms);
            //test.Save(fullFilename, ImageFormat.Jpeg);


        }



        /* Register iPhone: This method is first called by the iPhone when it connects to the 
         * server. Calling it for the first time causes a new iOSSocket to be created with a
         * new port number. It is then added to the list of devices and run in a thread. */
         

        [WebInvoke(Method = "POST", UriTemplate = "/{identifier}/register")]
        public int RegisteriPhone(String identifier)
        {


            if(!Devices.ContainsDevice(identifier))
            {
                

                //Create a new socket and readloop for the newly connected iOS device
                iOSSocket sc = new iOSSocket(identifier); 




          
                //Create the iOSDevice object for this connection
                iOSDevice dev = new iOSDevice(sc, identifier);

                Devices.AddNewDevice(dev); 



                //Start running this server in a new Thread
                Thread thread = new Thread(new ThreadStart(sc.RunServer));
                thread.Start();
                
                return sc.portNumber; 
                
            }
            else
            {

                iOSDevice device = Devices.GetDevice(identifier);
                return device.GetPortNumber();

            }
     
        }


        [WebInvoke(Method = "POST" , UriTemplate = "/{identifier}/deregister")]
        public void DeregisteriPhone(String identifier)
        {



            if(Devices.ContainsDevice(identifier))
            
            {
                Devices.RemoveDevice(identifier); 
                
            }

        
           
        }



        [WebInvoke(Method = "POST", UriTemplate = "/{identifier}/return/{messageID}/{returnValue}")]
        public void MethodCallReturn(String identifier, String messageID, String returnValue)
        {

            Debug.WriteLine("iPhone: " + identifier + "returns " + messageID + " of " + returnValue);

            iOSDevice device = Devices.GetDevice(identifier);



        }






    }
}
